home *** CD-ROM | disk | FTP | other *** search
-
- /* Copyright (c) Mark J. Kilgard, 1997. */
-
- /* This program is freely distributable without licensing fees
- and is provided without guarantee or warrantee expressed or
- implied. This program is -not- in the public domain. */
-
- #include <assert.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "glut.h"
- #include "glutint.h"
-
- char *__glutDisplayString = NULL;
-
- static AGLPixelFormat findMatch(Criterion *criteria, int ncriteria)
- {
- AGLPixelFormat format;
- GLint i, attrib[50], nattrib;
-
- nattrib = 0;
- for(i = 0; i < ncriteria; i++)
- {
- switch(criteria[i].capability)
- {
- case BUFFER_SIZE:
- attrib[nattrib++] = AGL_BUFFER_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case RGBA:
- attrib[nattrib++] = AGL_RGBA;
- break;
- case DOUBLEBUFFER:
- attrib[nattrib++] = AGL_DOUBLEBUFFER;
- break;
- case STEREO:
- attrib[nattrib++] = AGL_STEREO;
- break;
- case AUX_BUFFERS:
- attrib[nattrib++] = AGL_AUX_BUFFERS;
- attrib[nattrib++] = criteria[i].value;
- break;
- case RED_SIZE:
- attrib[nattrib++] = AGL_RED_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case GREEN_SIZE:
- attrib[nattrib++] = AGL_GREEN_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case BLUE_SIZE:
- attrib[nattrib++] = AGL_BLUE_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case ALPHA_SIZE:
- attrib[nattrib++] = AGL_ALPHA_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case DEPTH_SIZE:
- attrib[nattrib++] = AGL_DEPTH_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case STENCIL_SIZE:
- attrib[nattrib++] = AGL_STENCIL_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case ACCUM_RED_SIZE:
- attrib[nattrib++] = AGL_ACCUM_RED_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case ACCUM_GREEN_SIZE:
- attrib[nattrib++] = AGL_ACCUM_GREEN_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case ACCUM_BLUE_SIZE:
- attrib[nattrib++] = AGL_ACCUM_BLUE_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case ACCUM_ALPHA_SIZE:
- attrib[nattrib++] = AGL_ACCUM_ALPHA_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case LEVEL:
- attrib[nattrib++] = AGL_BUFFER_SIZE;
- attrib[nattrib++] = criteria[i].value;
- break;
- case CONFORMANT:
- break;
- case SAMPLES:
- break;
- case SLOW:
- break;
- }
- }
-
- //attrib[nattrib++] = AGL_FAILURE_REVERT;
- attrib[nattrib++] = AGL_NONE;
-
- format = aglChoosePixelFormat(NULL, 0, attrib);
-
- return format;
- }
-
-
- static int parseCriteria(char *word, Criterion * criterion, int *mask)
- {
- char *cstr, *vstr, *response;
- int comparator, value;
- int rgb, rgba, acc, acca, count, i;
-
- cstr = strpbrk(word, "=><!~");
- if (cstr)
- {
- switch (cstr[0])
- {
- case '=':
- comparator = EQ;
- vstr = &cstr[1];
- break;
- case '~':
- comparator = MIN;
- vstr = &cstr[1];
- break;
- case '>':
- if(cstr[1] == '=')
- {
- comparator = GTE;
- vstr = &cstr[2];
- }
- else
- {
- comparator = GT;
- vstr = &cstr[1];
- }
- break;
- case '<':
- if(cstr[1] == '=')
- {
- comparator = LTE;
- vstr = &cstr[2];
- }
- else
- {
- comparator = LT;
- vstr = &cstr[1];
- }
- break;
- case '!':
- if(cstr[1] == '=')
- {
- comparator = NEQ;
- vstr = &cstr[2];
- }
- else
- {
- return -1;
- }
- break;
- default:
- return -1;
- }
-
- value = (int) strtol(vstr, &response, 0);
-
- if(response == vstr)
- {
- /* Not a valid number. */
- return -1;
- }
-
- *cstr = '\0';
-
- }
- else
- {
- comparator = NONE;
- }
-
- switch(word[0])
- {
- case 'a':
- if(!strcmp(word, "alpha"))
- {
- criterion[0].capability = ALPHA_SIZE;
-
- if(comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
-
- *mask |= (1 << RGBA);
- *mask |= (1 << ALPHA_SIZE);
- *mask |= (1 << RGBA_MODE);
-
- return 1;
- }
-
- acca = !strcmp(word, "acca");
- acc = !strcmp(word, "acc");
-
- if(acc || acca)
- {
- criterion[0].capability = ACCUM_RED_SIZE;
- criterion[1].capability = ACCUM_GREEN_SIZE;
- criterion[2].capability = ACCUM_BLUE_SIZE;
- criterion[3].capability = ACCUM_ALPHA_SIZE;
-
- if(acca)
- {
- count = 4;
- }
- else
- {
- count = 3;
- criterion[3].comparison = MIN;
- criterion[3].value = 0;
- }
-
- if(comparator == NONE)
- {
- comparator = GTE;
- value = 8;
- }
-
- for(i = 0; i < count; i++)
- {
- criterion[i].comparison = comparator;
- criterion[i].value = value;
- }
-
- *mask |= (1 << ACCUM_RED_SIZE);
-
- return 4;
- }
-
- if(!strcmp(word, "auxbufs"))
- {
- criterion[0].capability = AUX_BUFFERS;
-
- if(comparator == NONE)
- {
- criterion[0].comparison = MIN;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
-
- *mask |= (1 << AUX_BUFFERS);
-
- return 1;
- }
-
- return -1;
- case 'b':
- if(!strcmp(word, "blue"))
- {
- criterion[0].capability = BLUE_SIZE;
-
- if (comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
-
- *mask |= (1 << RGBA);
- *mask |= (1 << RGBA_MODE);
-
- return 1;
- }
-
- if(!strcmp(word, "buffer"))
- {
- criterion[0].capability = BUFFER_SIZE;
-
- if(comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
-
- return 1;
- }
-
- return -1;
- case 'c':
- if (!strcmp(word, "conformant"))
- {
- criterion[0].capability = CONFORMANT;
- if (comparator == NONE)
- {
- criterion[0].comparison = EQ;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << CONFORMANT);
- return 1;
- }
- return -1;
- case 'd':
- if (!strcmp(word, "depth"))
- {
- criterion[0].capability = DEPTH_SIZE;
- if (comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 12;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << DEPTH_SIZE);
- return 1;
- }
- if (!strcmp(word, "double"))
- {
- criterion[0].capability = DOUBLEBUFFER;
- if (comparator == NONE) {
- criterion[0].comparison = EQ;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << DOUBLEBUFFER);
- return 1;
- }
- return -1;
- case 'f':
- if (!strcmp(word, "fullscreen"))
- {
- criterion[0].capability = FULLSCREEN;
- if (comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 12;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << FULLSCREEN);
- return 1;
- }
- return -1;
- case 'g':
- if (!strcmp(word, "green"))
- {
- criterion[0].capability = GREEN_SIZE;
- if (comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << RGBA);
- *mask |= (1 << RGBA_MODE);
- return 1;
- }
- return -1;
- case 'i':
- if (!strcmp(word, "index"))
- {
- criterion[0].capability = RGBA;
- criterion[0].comparison = EQ;
- criterion[0].value = 0;
- *mask |= (1 << RGBA);
- *mask |= (1 << CI_MODE);
- if (comparator == NONE)
- {
- criterion[1].capability = BUFFER_SIZE;
- criterion[1].comparison = GTE;
- criterion[1].value = 1;
- }
- else
- {
- criterion[1].capability = BUFFER_SIZE;
- criterion[1].comparison = comparator;
- criterion[1].value = value;
- }
- return 2;
- }
- return -1;
- case 'n':
- if (!strcmp(word, "num"))
- {
- criterion[0].capability = NUM;
- if (comparator == NONE)
- {
- return -1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- return 1;
- }
- }
- return -1;
- case 'r':
- if (!strcmp(word, "red"))
- {
- criterion[0].capability = RED_SIZE;
- if (comparator == NONE)
- {
- criterion[0].comparison = GTE;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << RGBA);
- *mask |= (1 << RGBA_MODE);
- return 1;
- }
- rgba = !strcmp(word, "rgba");
- rgb = !strcmp(word, "rgb");
- if (rgb || rgba)
- {
- criterion[0].capability = RGBA;
- criterion[0].comparison = EQ;
- criterion[0].value = 1;
-
- criterion[1].capability = RED_SIZE;
- criterion[2].capability = GREEN_SIZE;
- criterion[3].capability = BLUE_SIZE;
- criterion[4].capability = ALPHA_SIZE;
- if (rgba)
- {
- count = 5;
- }
- else
- {
- count = 4;
- criterion[4].comparison = MIN;
- criterion[4].value = 0;
- }
- if (comparator == NONE)
- {
- comparator = GTE;
- value = 1;
- }
- for (i = 1; i < count; i++)
- {
- criterion[i].comparison = comparator;
- criterion[i].value = value;
- }
- *mask |= (1 << RGBA);
- *mask |= (1 << RGBA_MODE);
- return 5;
- }
- return -1;
- case 's':
- if (!strcmp(word, "stencil"))
- {
- criterion[0].capability = STENCIL_SIZE;
- if (comparator == NONE) {
- criterion[0].comparison = MIN;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << STENCIL_SIZE);
- return 1;
- }
- if (!strcmp(word, "single"))
- {
- criterion[0].capability = DOUBLEBUFFER;
- if (comparator == NONE) {
- criterion[0].comparison = EQ;
- criterion[0].value = 0;
- *mask |= (1 << DOUBLEBUFFER);
- return 1;
- }
- else
- {
- return -1;
- }
- }
- if (!strcmp(word, "stereo"))
- {
- criterion[0].capability = STEREO;
- if (comparator == NONE)
- {
- criterion[0].comparison = EQ;
- criterion[0].value = 1;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << STEREO);
- return 1;
- }
- if (!strcmp(word, "samples"))
- {
- criterion[0].capability = SAMPLES;
- if (comparator == NONE) {
- criterion[0].comparison = LTE;
- criterion[0].value = 4;
- }
- else
- {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << SAMPLES);
- return 1;
- }
- if (!strcmp(word, "slow"))
- {
- criterion[0].capability = SLOW;
- if (comparator == NONE) {
- /* Just "slow" means permit fast visuals, but accept
- slow ones in preference. Presumably the slow ones
- must be higher quality or something else desirable. */
- criterion[0].comparison = GTE;
- criterion[0].value = 0;
- } else {
- criterion[0].comparison = comparator;
- criterion[0].value = value;
- }
- *mask |= (1 << SLOW);
- return 1;
- }
- return -1;
- default:
- return -1;
- }
- }
-
- static Criterion *parseModeString(char *mode, int *ncriteria)
- {
- Criterion *criteria = NULL;
- int n, mask, parsed;
- char *copy, *word;
-
- copy = __glutStrdup(mode);
-
- /* Attempt to estimate how many criteria entries should be needed. */
- n = 0;
- word = strtok(copy, " \t");
- while(word)
- {
- n++;
- word = strtok(NULL, " \t");
- }
-
- /* Overestimate by 4 times ("rgba" might add four criteria
- entries) plus add in possible defaults plus space for
- required criteria. */
- criteria = (Criterion *) malloc((4 * n + 30) * sizeof(Criterion));
- if (!criteria) __glutFatalError("out of memory.");
-
- /* Re-copy the copy of the mode string. */
- strcpy(copy, mode);
-
- mask = 0;
- n = 0;
-
- word = strtok(copy, " \t");
- while(word)
- {
- parsed = parseCriteria(word, &criteria[n], &mask);
-
- if(parsed >= 0)
- {
- n += parsed;
- }
- else
- {
- __glutWarning("Unrecognized display string word: %s (ignoring)\n", word);
- }
-
- word = strtok(NULL, " \t");
- }
-
- if(n)
- {
- criteria = (Criterion *) realloc(criteria, n * sizeof(Criterion));
-
- if(!criteria) __glutFatalError("out of memory.");
- }
- else
- {
- free(criteria);
- criteria = NULL;
- }
-
- free(copy);
- *ncriteria = n;
-
- return criteria;
- }
-
- AGLPixelFormat __glutVisualInfoFromString(char *string)
- {
- Criterion *criteria;
- AGLPixelFormat visinfo;
- int ncriteria;
-
- criteria = parseModeString(string, &ncriteria);
- if(criteria == NULL)
- {
- __glutWarning("failed to parse mode string");
- return NULL;
- }
-
- visinfo = findMatch(criteria, ncriteria);
-
- free(criteria);
-
- return visinfo;
- }
-
- void glutInitDisplayString(const char *string)
- {
- if(__glutDisplayString)
- {
- free(__glutDisplayString);
- }
-
- if(string)
- {
- __glutDisplayString = __glutStrdup(string);
-
- if(!__glutDisplayString) __glutFatalError("out of memory.");
- }
- else
- {
- __glutDisplayString = NULL;
- }
- }
-